﻿using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace VMExplorer.Win32
{
	// Threads
	partial class Native
	{
		#region :: Enums ::

		public enum THREAD_INFORMATION_CLASS
		{
			ThreadBasicInformation,
			ThreadTimes,
			ThreadPriority,
			ThreadBasePriority,
			ThreadAffinityMask,
			ThreadImpersonationToken,
			ThreadDescriptorTableEntry,
			ThreadEnableAlignmentFaultFixup,
			ThreadEventPair,
			ThreadQuerySetWin32StartAddress,
			ThreadZeroTlsCell,
			ThreadPerformanceCount,
			ThreadAmILastThread,
			ThreadIdealProcessor,
			ThreadPriorityBoost,
			ThreadSetTlsArrayAddress,
			ThreadIsIoPending,
			ThreadHideFromDebugger
		}

		[Flags]
		public enum ThreadAccess : int
		{
			TERMINATE = (0x0001),
			SUSPEND_RESUME = (0x0002),
			GET_CONTEXT = (0x0008),
			SET_CONTEXT = (0x0010),
			SET_INFORMATION = (0x0020),
			QUERY_INFORMATION = (0x0040),
			SET_THREAD_TOKEN = (0x0080),
			IMPERSONATE = (0x0100),
			DIRECT_IMPERSONATION = (0x0200)
		}

		#endregion
		#region :: Structs ::

		[StructLayout (LayoutKind.Sequential, Size = 0x1C)]
		public struct THREAD_BASIC_INFORMATION
		{
			public Int32 ExitStatus;      // NTSTATUS
			public IntPtr TebBaseAddress; // PVOID
			public UInt32 processID;
			public UInt32 threadID;
			public UInt32 AffinityMask;   // KAFFINITY
			public UInt32 Priority;       // KPRIORITY
			public UInt32 BasePriority;   // KPRIORITY
		}

		[StructLayout (LayoutKind.Explicit, Size = 0xfb8)]
		public struct TEB
		{
			[Description ("Head of exception record list")]
			[FieldOffset (0x000)]
			public IntPtr ExceptionList;         // 00h (PEXCEPTION_REGISTRATION_RECORD) Head of exception record list

			[Description ("Top of user stack")]
			[FieldOffset (0x004)]
			public IntPtr StackBase;          // 04h (PVOID) Top of user stack

			[Description ("Base of user stack")]
			[FieldOffset (0x008)]
			public IntPtr StackLimit;         // 08h (PVOID) Base of user stack
			[FieldOffset (0x00C)]
			public IntPtr SubSystemTib;       // 0Ch (PVOID) 
			[FieldOffset (0x010)]
			public IntPtr FiberData;          // 10h (ULONG)
			[FieldOffset (0x010)]
			public UInt32 Version;            // 10h (ULONG)

			[Description ("Available for application use")]
			[FieldOffset (0x014)]
			public IntPtr ArbitraryUserPointer;        // 14h (PVOID) Available for application use

			[Description ("Linear address of this structure")]
			[FieldOffset (0x018)]
			public IntPtr Self;               // 18h (PTIB) Linear address of TIB structure

			[FieldOffset (0x01C)]
			public UInt32 EnvironmentPointer; // 1Ch (PVOID)
			[FieldOffset (0x020)]
			public UInt32 ProcessID;          // 20h (DWORD)
			[FieldOffset (0x024)]
			public UInt32 ThreadID;           // 24h (DWORD)
			[FieldOffset (0x028)]
			public UInt32 ActiveRpcHandle;    // 28h (PVOID)

			[Description ("Thread Local Storage array")]
			[FieldOffset (0x02C)]
			public IntPtr TLSArray;         // 2Ch (PVOID*) Thread Local Storage array

			[Description ("Linear address of PEB structure")]
			[FieldOffset (0x030)]
			public IntPtr ProcessEnvironmentBlock;               // 30h (PPEB) Linear address of PEB structure

			[Description ("Last error number")]
			[FieldOffset (0x034)]
			public UInt32 LastErrorValue;        // 34h (DWORD) Last error number
			[FieldOffset (0x038)]
			public UInt32 CountOfOwnedCriticalSections;       // 38h (DWORD) Last status number

			[FieldOffset (0x03C)]
			public UInt32 CsrClientThread;            // 3Ch (DWORD) Count owned locks
			[FieldOffset (0x040)]
			public IntPtr Win32ThreadInfo;      // 40h (DWORD) Hard error mode
			[MarshalAs (UnmanagedType.ByValArray, SizeConst = 26)]
			[FieldOffset (0x044)]
			public UInt32[] User32Reserved; // Uint4B * 26
			[MarshalAs (UnmanagedType.ByValArray, SizeConst = 5)]
			[FieldOffset (0x0ac)]
			public UInt32[] UserReserved; // Uint4B * 5
			[FieldOffset (0x0c0)]
			public IntPtr WOW32Reserved; // Ptr32 Void
			[FieldOffset (0x0c4)]
			public UInt32 CurrentLocale; // Uint4B
			[FieldOffset (0x0c8)]
			public UInt32 FpSoftwareStatusRegister; // Uint4B
			[MarshalAs (UnmanagedType.ByValArray, SizeConst = 54)]
			[FieldOffset (0x0cc)]
			public IntPtr[] SystemReserved1; // Ptr32 Void * 54
			[FieldOffset (0x1a4)]
			public Int32 ExceptionCode; // Int4B
			//TODO
			//[FieldOffset (0x1a8)]
			//public _ACTIVATION_CONTEXT_STACK ActivationContextStack; // _ACTIVATION_CONTEXT_STACK
			[MarshalAs (UnmanagedType.ByValArray, SizeConst = 24)]
			[FieldOffset (0x1bc)]
			public Byte[] SpareBytes1; // UChar * 24
			//TODO
			//[FieldOffset (0x1d4)]
			//public _GDI_TEB_BATCH GdiTebBatch; // _GDI_TEB_BATCH
			[FieldOffset (0x6b4)]
			public UInt32 RealProcessID;          // _CLIENT_ID
			[FieldOffset (0x6b8)]
			public UInt32 RealThreadID;           // _CLIENT_ID
			[FieldOffset (0x6bc)]
			public IntPtr GdiCachedProcessHandle; // Ptr32 Void
			[FieldOffset (0x6c0)]
			public UInt32 GdiClientPID; // Uint4B
			[FieldOffset (0x6c4)]
			public UInt32 GdiClientTID; // Uint4B
			[FieldOffset (0x6c8)]
			public IntPtr GdiThreadLocalInfo; // Ptr32 Void
			[MarshalAs (UnmanagedType.ByValArray, SizeConst = 62)]
			[FieldOffset (0x6cc)]
			public UInt32[] Win32ClientInfo; // Uint4B * 62
			[MarshalAs (UnmanagedType.ByValArray, SizeConst = 233)]
			[FieldOffset (0x7c4)]
			public IntPtr[] glDispatchTable; // Ptr32 Void * 233
			[MarshalAs (UnmanagedType.ByValArray, SizeConst = 29)]
			[FieldOffset (0xb68)]
			public UInt32[] glReserved1; // Uint4B * 29
			[FieldOffset (0xbdc)]
			public IntPtr glReserved2; // Ptr32 Void
			[FieldOffset (0xbe0)]
			public IntPtr glSectionInfo; // Ptr32 Void
			[FieldOffset (0xbe4)]
			public IntPtr glSection; // Ptr32 Void
			[FieldOffset (0xbe8)]
			public IntPtr glTable; // Ptr32 Void
			[FieldOffset (0xbec)]
			public IntPtr glCurrentRC; // Ptr32 Void
			[FieldOffset (0xbf0)]
			public IntPtr glContext; // Ptr32 Void
			[FieldOffset (0xbf4)]
			public UInt32 LastStatusValue; // Uint4B
			[FieldOffset (0xbf8)]
			public UNICODE_STRING StaticUnicodeString; // _UNICODE_STRING
			[FieldOffset (0xe0c)]
			public IntPtr DeallocationStack; // Ptr32 Void
			[MarshalAs (UnmanagedType.ByValArray, SizeConst = 64)]
			[FieldOffset (0xe10)]
			public IntPtr[] TlsSlots; // Ptr32 Void * 64
			[FieldOffset (0xf10)]
			public LIST_ENTRY TlsLinks; // _LIST_ENTRY
			[FieldOffset (0xf18)]
			public IntPtr Vdm; // Ptr32 Void
			[FieldOffset (0xf1c)]
			public IntPtr ReservedForNtRpc; // Ptr32 Void
			[MarshalAs (UnmanagedType.ByValArray, SizeConst = 2)]
			[FieldOffset (0xf20)]
			public IntPtr[] DbgSsReserved; // Ptr32 Void * 2
			[FieldOffset (0xf28)]
			public UInt32 HardErrorsAreDisabled; // Uint4B
			[MarshalAs (UnmanagedType.ByValArray, SizeConst = 16)]
			[FieldOffset (0xf2c)]
			public IntPtr[] Instrumentation; // Ptr32 Void * 16
			[FieldOffset (0xf6c)]
			public IntPtr WinSockData; // Ptr32 Void
			[FieldOffset (0xf70)]
			public UInt32 GdiBatchCount; // Uint4B
			[FieldOffset (0xf74)]
			public Byte InDbgPrint; // UChar
			[FieldOffset (0xf75)]
			public Byte FreeStackOnTermination; // UChar
			[FieldOffset (0xf76)]
			public Byte HasFiberData; // UChar
			[FieldOffset (0xf77)]
			public Byte IdealProcessor; // UChar
			[FieldOffset (0xf78)]
			public UInt32 Spare3; // Uint4B
			[FieldOffset (0xf7c)]
			public IntPtr ReservedForPerf; // Ptr32 Void
			[FieldOffset (0xf80)]
			public IntPtr ReservedForOle; // Ptr32 Void
			[FieldOffset (0xf84)]
			public UInt32 WaitingOnLoaderLock; // Uint4B
			[FieldOffset (0xf88)]
			public Wx86ThreadState Wx86Thread; // _Wx86ThreadState
			[FieldOffset (0xf94)]
			public IntPtr TlsExpansionSlots; // Ptr32 Ptr32 Void
			[FieldOffset (0xf98)]
			public UInt32 ImpersonationLocale; // Uint4B
			[FieldOffset (0xf9c)]
			public UInt32 IsImpersonating; // Uint4B
			[FieldOffset (0xfa0)]
			public IntPtr NlsCache; // Ptr32 Void
			[FieldOffset (0xfa4)]
			public IntPtr pShimData; // Ptr32 Void
			[FieldOffset (0xfa8)]
			public UInt32 HeapVirtualAffinity; // Uint4B
			[FieldOffset (0xfac)]
			public IntPtr CurrentTransactionHandle; // Ptr32 Void
			[FieldOffset (0xfb0)]
			public IntPtr ActiveFrame; // Ptr32 _TEB_ACTIVE_FRAME
			[FieldOffset (0xfb4)]
			public Byte SafeThunkCall; // UChar
			//[MarshalAs (UnmanagedType.ByValArray, SizeConst = 3)]
			//[FieldOffset (0xfb5)]
			//public Byte[] BooleanSpare; // UChar * 3
		};

		[StructLayout (LayoutKind.Sequential, Size = 0x0C)]
		public struct Wx86ThreadState
		{
			public IntPtr  CallBx86Eip; // Ptr32 to Uint4B
			public IntPtr  DeallocationCpu; // Ptr32 to Void
			public Byte  UseKnownWx86Dll; // UChar
			public Byte  OleStubInvoked; // Char
		};

		#endregion
		#region :: API ::

		[DllImport ("kernel32.dll")]
		public static extern IntPtr OpenThread (ThreadAccess DesiredAccess, bool InheritHandle, int ThreadId);

		[DllImport ("ntdll.dll", SetLastError = true)]
		public static extern UInt32 NtQueryInformationThread (IntPtr ThreadHandle, THREAD_INFORMATION_CLASS ThreadInformationClass, IntPtr ThreadInformation, UInt32 ThreadInformationLength, ref UInt32 ReturnLength);
		
		//[DllImport ("kernel32.dll")]
		//public static extern int SuspendThread (IntPtr hThread);
		//[DllImport ("kernel32.dll")]
		//public static extern int ResumeThread (IntPtr hThread);
		//[DllImport ("kernel32.dll")]
		//public static extern int GetCurrentThreadId ();

		#endregion
	}
}